/*
 * %W% %E%
 *
 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package com.sun.corba.se.impl.protocol;

import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;

import com.sun.corba.se.pept.protocol.ClientRequestDispatcher ;

import com.sun.corba.se.spi.protocol.LocalClientRequestDispatcher ;
import com.sun.corba.se.spi.protocol.LocalClientRequestDispatcherFactory ;
import com.sun.corba.se.spi.protocol.CorbaServerRequestDispatcher ;
import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry ;

import com.sun.corba.se.spi.oa.ObjectAdapterFactory ;

import com.sun.corba.se.spi.orb.ORB ;

import com.sun.corba.se.impl.orbutil.ORBConstants ;
import com.sun.corba.se.impl.orbutil.DenseIntMapImpl ;

/**
 * This is a registry of all subcontract ID dependent objects.  This includes:
 * LocalClientRequestDispatcherFactory, ClientRequestDispatcher, ServerSubcontract, and 
 * ObjectAdapterFactory. 
 */
public class RequestDispatcherRegistryImpl implements RequestDispatcherRegistry {
    private ORB orb;

    protected int defaultId;			// The default subcontract ID to use if 
						// there is no more specific ID available.
						// This happens when invoking a foreign IOR.
    private DenseIntMapImpl SDRegistry ;	// ServerRequestDispatcher registry
    private DenseIntMapImpl CSRegistry ;	// ClientRequestDispatcher registry
    private DenseIntMapImpl OAFRegistry ;	// ObjectAdapterFactory registry
    private DenseIntMapImpl LCSFRegistry ;	// LocalClientRequestDispatcherFactory registry
    private Set objectAdapterFactories ;	// Set of all ObjectAdapterFactory instances
    private Set objectAdapterFactoriesView ;	// Read-only view of oaf instances
    private Map stringToServerSubcontract ;	// Map from obect key string to 
						// ServerSubcontract
						// for special bootstrap IORs

    public RequestDispatcherRegistryImpl(ORB orb, int defaultId ) 
    {
	this.orb = orb;
        this.defaultId = defaultId;
        SDRegistry = new DenseIntMapImpl() ;
        CSRegistry = new DenseIntMapImpl() ;
	OAFRegistry = new DenseIntMapImpl() ;
	LCSFRegistry = new DenseIntMapImpl() ;
	objectAdapterFactories = new HashSet() ;
	objectAdapterFactoriesView = Collections.unmodifiableSet( objectAdapterFactories ) ;
	stringToServerSubcontract = new HashMap() ;
    }

    public synchronized void registerClientRequestDispatcher( 
	ClientRequestDispatcher csc, int scid)
    {
	CSRegistry.set( scid, csc ) ;
    }

    public synchronized void registerLocalClientRequestDispatcherFactory( 
	LocalClientRequestDispatcherFactory csc, int scid)
    {
	LCSFRegistry.set( scid, csc ) ;
    }

    public synchronized void registerServerRequestDispatcher( 
	CorbaServerRequestDispatcher ssc, int scid)
    {
	SDRegistry.set( scid, ssc ) ;
    }

    public synchronized void registerServerRequestDispatcher(
	CorbaServerRequestDispatcher scc, String name )
    {
	stringToServerSubcontract.put( name, scc ) ;
    }

    public synchronized void registerObjectAdapterFactory( 
	ObjectAdapterFactory oaf, int scid)
    {
	objectAdapterFactories.add( oaf ) ;
	OAFRegistry.set( scid, oaf ) ;
    }

    // **************************************************
    // Methods to find the subcontract side subcontract
    // **************************************************

    // Note that both forms of getServerRequestDispatcher need to return
    // the default server delegate if no other match is found.
    // This is essential to proper handling of errors for 
    // malformed requests.  In particular, a bad MAGIC will
    // result in a lookup in the named key table (stringToServerSubcontract),
    // which must return a valid ServerRequestDispatcher.  A bad subcontract ID
    // will similarly need to return the default ServerRequestDispatcher.
    
    public CorbaServerRequestDispatcher getServerRequestDispatcher(int scid)
    {
	CorbaServerRequestDispatcher sdel =
	    (CorbaServerRequestDispatcher)(SDRegistry.get(scid)) ;
	if ( sdel == null )
            sdel = (CorbaServerRequestDispatcher)(SDRegistry.get(defaultId)) ;

	return sdel;
    }

    public CorbaServerRequestDispatcher getServerRequestDispatcher( String name ) 
    {
	CorbaServerRequestDispatcher sdel =
	    (CorbaServerRequestDispatcher)stringToServerSubcontract.get( name ) ;

	if ( sdel == null )
            sdel = (CorbaServerRequestDispatcher)(SDRegistry.get(defaultId)) ;

	return sdel;
    }

    public LocalClientRequestDispatcherFactory getLocalClientRequestDispatcherFactory( 
	int scid )
    {
	LocalClientRequestDispatcherFactory factory = 
	    (LocalClientRequestDispatcherFactory)(LCSFRegistry.get(scid)) ;
	if (factory == null) {
	    factory = (LocalClientRequestDispatcherFactory)(LCSFRegistry.get(defaultId)) ;
	}

	return factory ;
    }

    public ClientRequestDispatcher getClientRequestDispatcher( int scid )
    {
	ClientRequestDispatcher subcontract = 
	    (ClientRequestDispatcher)(CSRegistry.get(scid)) ;
	if (subcontract == null) {
	    subcontract = (ClientRequestDispatcher)(CSRegistry.get(defaultId)) ;
	}

	return subcontract ;
    }

    public ObjectAdapterFactory getObjectAdapterFactory( int scid )
    {
	ObjectAdapterFactory oaf =
            (ObjectAdapterFactory)(OAFRegistry.get(scid)) ;
	if ( oaf == null )
            oaf = (ObjectAdapterFactory)(OAFRegistry.get(defaultId)) ;

	return oaf;
    }

    public Set getObjectAdapterFactories() 
    {
	return objectAdapterFactoriesView ;
    }
}
